"""EEG数据服务层

处理脑波数据相关的业务逻辑
专注于数据接收和存储，支持时序数据处理
"""

import json
from datetime import datetime
from typing import Optional, Dict, List, Any
from loguru import logger

from app.config import settings
from app.models.brain_wave import BrainWave
from app.models.sleep_monitoring_metrics import SleepMonitoringMetrics
from app.schemas.eeg_upload_schemas import EEGUploadRequest
from app.schemas.analysis_schemas import AnalysisResultRequest, AnalysisResultResponse
from app.services.simple_time_buffer import SimpleTimeBuffer


class EEGService:
    """EEG数据服务类
    
    专注于数据接收和存储，支持时序数据处理
    """
    
    def __init__(self):
        """初始化EEG服务"""
        # 初始化时序缓冲器
        self._time_buffer = SimpleTimeBuffer(
            flush_interval=30  # 30秒刷新一次
        )
        # 设置数据刷新回调
        self._time_buffer.set_flush_callback(self._flush_ordered_data_to_db)
        logger.info("EEG服务初始化完成，时序缓冲器已启动")
    
    async def receive_raw_data(self, request: EEGUploadRequest) -> Dict:
        """接收原始脑波数据并直接存储到数据库
        
        Args:
            request: EEG数据上传请求
            
        Returns:
            Dict: 处理结果
        """
        try:
            logger.info(f"接收到EEG数据: session_id={request.id}, "
                       f"timestamp={request.data_timestamp}, sequence={request.sequence_number}")
            
            # 验证时序信息
            if not request.data_timestamp:
                logger.warning(f"EEG数据缺少时间戳: session_id={request.id}")
                # 如果没有时间戳，使用当前时间
                request.data_timestamp = datetime.now().timestamp()
            
            # 直接保存到数据库
            await self._save_eeg_data_to_db(request)
            
            return {
                "status": "success",
                "message": "EEG数据已直接保存到数据库",
                "session_id": request.id,
                "timestamp": request.data_timestamp,
                "sequence_number": request.sequence_number
            }
            
        except Exception as e:
            logger.error(f"接收EEG数据失败: {str(e)}")
            return {
                "status": "error",
                "message": f"接收EEG数据失败: {str(e)}"
            }
    
    async def receive_analysis_data(self, request: AnalysisResultRequest) -> Dict:
        """接收分析结果数据并存储到内存缓存
        
        数据会在内存中保留30秒，提供其他服务查询功能
        
        Args:
            request: 分析结果请求
            
        Returns:
            dict: 接收结果
        """
        try:
            # 将数据添加到时序缓冲器（用于内存缓存）
            # 使用第一个数据点的时间戳
            timestamp = request.data[0].timestamp if request.data else datetime.now().timestamp()
            
            self._time_buffer.add_data({
                "session_id": request.session_id,
                "timestamp": timestamp,
                "data": request,
                "data_type": "analysis_result"
            })
            
            logger.info(f"分析数据已加入内存缓存: {request.session_id}")
            
            return {
                "success": True,
                "id": request.session_id,
                "cached_at": datetime.now().isoformat(),
                "message": "分析数据已加入内存缓存"
            }
            
        except Exception as e:
            logger.error(f"缓存分析数据失败: {str(e)}")
            raise
    
    async def get_history_data(
        self,
        id: Optional[str] = None,
        room_id: Optional[str] = None,
        user_id: Optional[str] = None,
        limit: int = settings.default_query_limit
    ) -> Dict:
        """查询历史数据
        
        简化的历史数据查询
        
        Args:
            id: 会话ID
            room_id: 房间ID
            user_id: 用户ID
            limit: 返回记录数量限制
            
        Returns:
            dict: 历史数据
        """
        try:
            # 构建查询条件
            query = BrainWave.select()
            
            if id:
                query = query.where(BrainWave.id == id)
            if room_id:
                query = query.where(BrainWave.room_id == room_id)
            if user_id:
                query = query.where(BrainWave.user_id == user_id)
            
            # 执行查询
            results = list(query.order_by(BrainWave.start_time.desc()).limit(limit))
            
            # 转换为字典格式
            history_data = []
            for brain_wave in results:
                data = {
                    "id": brain_wave.id,
                    "session_id": brain_wave.session_id,
                    "room_id": brain_wave.room_id,
                    "user_id": brain_wave.user_id,
                    "start_time": brain_wave.start_time.isoformat() if brain_wave.start_time else None,
                    "end_time": brain_wave.end_time.isoformat() if brain_wave.end_time else None,
                    "created_at": brain_wave.created_at.isoformat() if brain_wave.created_at else None
                }
                history_data.append(data)
            
            logger.info(f"查询到 {len(history_data)} 条历史数据")
            
            return {
                "success": True,
                "data": history_data,
                "count": len(history_data),
                "query_time": datetime.now().isoformat()
            }
            
        except Exception as e:
            logger.error(f"查询历史数据失败: {str(e)}")
            raise
    
    async def get_session_data(self, session_id: str) -> Optional[dict]:
        """获取会话数据
        
        Args:
            session_id: 会话ID
            
        Returns:
            dict: 会话数据，如果不存在则返回None
        """
        try:
            brain_wave = BrainWave.get_or_none(BrainWave.id == session_id)
            if not brain_wave:
                logger.warning(f"会话不存在: {session_id}")
                return None
        except Exception as e:
            logger.error(f"获取会话数据失败: {e}")
            return None
    
    def _flush_ordered_data_to_db(self, session_id: str, ordered_data: List[Dict]) -> None:
        """将有序数据刷新到数据库或内存缓存
        
        Args:
            session_id: 会话ID
            ordered_data: 按时间戳排序的数据列表
        """
        if not ordered_data:
            logger.warning(f"会话 {session_id}: 没有数据需要刷新")
            return
            
        try:
            logger.info(f"会话 {session_id}: 开始处理 {len(ordered_data)} 条有序数据")
            
            success_count = 0
            for data_item in ordered_data:
                try:
                    data = data_item['data']
                    data_type = data_item['data_type']
                    
                    if data_type == "eeg_raw":
                        # EEG原始数据直接保存到数据库
                        self._save_eeg_data_to_db_sync(data)
                        success_count += 1
                    elif data_type == "analysis_result":
                        # 分析结果数据在30秒后保存到数据库
                        self._save_analysis_data_to_db_sync(data)
                        logger.info(f"分析数据已从内存缓存刷新到数据库: {data.session_id}")
                        success_count += 1
                    else:
                        logger.warning(f"会话 {session_id}: 未知数据类型 {data_type}")
                        continue
                        
                except Exception as item_error:
                    logger.error(f"会话 {session_id}: 处理单条数据失败: {item_error}")
                    # 继续处理其他数据，不中断整个批次
                    
            logger.info(f"会话 {session_id}: 成功处理 {success_count}/{len(ordered_data)} 条数据")
            
        except Exception as e:
            logger.error(f"处理数据失败: {str(e)}")
            raise
    
    def _save_eeg_data_to_db_sync(self, request: EEGUploadRequest) -> None:
        """保存EEG数据到数据库（同步版本）
        
        实现会话级别的数据累积存储：
        - 如果会话不存在，创建新记录
        - 如果会话存在，追加新数据到现有记录
        
        Args:
            request: EEG数据上传请求
        """
        try:
            # 检查会话是否存在
            brain_wave = BrainWave.get_or_none(BrainWave.id == int(request.id))
            
            if not brain_wave:
                # 创建新的会话记录，使用request.id作为主键
                brain_wave = BrainWave.create(
                    id=int(request.id),
                    room_id=request.room_id,
                    user_id=None,  # 可以从request中获取，如果有的话
                    start_time=datetime.now(),
                    total_seconds=0
                )
                logger.info(f"创建新的脑波会话: {brain_wave.id}")
            else:
                logger.info(f"找到现有会话，准备追加数据: {brain_wave.id}")
            
            # 更新room_id（如果提供了新的值）
            if request.room_id and brain_wave.room_id != request.room_id:
                brain_wave.room_id = request.room_id
            
            # 定义频段映射
            frequency_bands = {
                'eeg_wave_data': request.eeg_wave_data,
                'delta_data': request.delta_data,
                'theta_data': request.theta_data,
                'low_alpha_data': request.low_alpha_data,
                'high_alpha_data': request.high_alpha_data,
                'low_beta_data': request.low_beta_data,
                'high_beta_data': request.high_beta_data,
                'low_gamma_data': request.low_gamma_data,
                'mid_gamma_data': request.mid_gamma_data
            }
            
            # 追加各频段数据
            for field_name, band_data in frequency_bands.items():
                if band_data:
                    # 构建新数据格式
                    new_data = {
                        "frame_rate": band_data.frame_rate if band_data.frame_rate is not None else (512 if field_name == 'eeg_wave_data' else 1),
                        "wave": {
                            "frames": band_data.wave.frames
                        },
                        "filtered": {
                            "frames": band_data.filtered.frames
                        }
                    }
                    
                    # 追加数据到现有记录
                    brain_wave.append_wave_data(field_name, new_data)
            
            # 更新会话时长
            if request.data_timestamp:
                end_timestamp = request.data_timestamp + (request.duration_seconds or 10.0)
                brain_wave.update_session_duration(end_timestamp)
            
            # 保存更新
            brain_wave.save()
            
            logger.info(f"EEG数据已追加到会话: {brain_wave.id}, 时长: {brain_wave.total_seconds}秒")
            
        except Exception as e:
            logger.error(f"保存EEG数据到数据库失败: {str(e)}")
            raise
    
    def _save_analysis_data_to_db_sync(self, request) -> None:
        """保存分析数据到数据库（同步版本）
        
        Args:
            request: 分析结果请求
        """
        try:
            # 处理AnalysisResultRequest对象，遍历其data列表
            for data_point in request.data:
                SleepMonitoringMetrics.create(
                    session_id=request.session_id,
                    room_id=request.room_id,
                    user_id=request.user_id,
                    analysis_time=datetime.fromtimestamp(data_point.timestamp),
                    sleep_state=data_point.state,
                    frequency_ratios=json.dumps({
                        'delta': data_point.delta,
                        'theta': data_point.theta,
                        'alpha': data_point.alpha,
                        'beta': data_point.beta,
                        'gamma': data_point.gamma
                    }),
                    quality_score=data_point.confidence,
                    recommendations=json.dumps([])
                )
            
            logger.info(f"分析数据已保存到数据库: {request.session_id}, 数据点数量: {len(request.data)}")
            
        except Exception as e:
            logger.error(f"保存分析数据失败: {str(e)}")
            raise

    async def _save_eeg_data_to_db(self, request: EEGUploadRequest) -> None:
        """保存EEG数据到数据库
        
        实现会话级别的数据累积存储：
        - 如果会话不存在，创建新记录
        - 如果会话存在，追加新数据到现有记录
        
        Args:
            request: EEG数据上传请求
        """
        try:
            # 检查会话是否存在
            brain_wave = BrainWave.get_or_none(BrainWave.id == int(request.id))
            
            if not brain_wave:
                # 创建新的会话记录，使用request.id作为主键
                brain_wave = BrainWave.create(
                    id=int(request.id),
                    room_id=request.room_id,
                    user_id=None,  # 可以从request中获取，如果有的话
                    start_time=datetime.now(),
                    total_seconds=0
                )
                logger.info(f"创建新的脑波会话: {brain_wave.id}")
            else:
                logger.info(f"找到现有会话，准备追加数据: {brain_wave.id}")
            
            # 更新room_id（如果提供了新的值）
            if request.room_id and brain_wave.room_id != request.room_id:
                brain_wave.room_id = request.room_id
            
            # 定义频段映射
            frequency_bands = {
                'eeg_wave_data': request.eeg_wave_data,
                'delta_data': request.delta_data,
                'theta_data': request.theta_data,
                'low_alpha_data': request.low_alpha_data,
                'high_alpha_data': request.high_alpha_data,
                'low_beta_data': request.low_beta_data,
                'high_beta_data': request.high_beta_data,
                'low_gamma_data': request.low_gamma_data,
                'mid_gamma_data': request.mid_gamma_data
            }
            
            # 追加各频段数据
            for field_name, band_data in frequency_bands.items():
                if band_data:
                    # 构建新数据格式
                    new_data = {
                        "frame_rate": band_data.frame_rate if band_data.frame_rate is not None else (512 if field_name == 'eeg_wave_data' else 1),
                        "wave": {
                            "frames": band_data.wave.frames
                        },
                        "filtered": {
                            "frames": band_data.filtered.frames
                        }
                    }
                    
                    # 追加数据到现有记录
                    brain_wave.append_wave_data(field_name, new_data)
            
            # 更新会话时长
            if request.data_timestamp:
                end_timestamp = request.data_timestamp + (request.duration_seconds or 10.0)
                brain_wave.update_session_duration(end_timestamp)
            
            # 保存更新
            brain_wave.save()
            
            logger.info(f"EEG数据已追加到会话: {brain_wave.id}, 时长: {brain_wave.total_seconds}秒")
            
        except Exception as e:
            logger.error(f"保存EEG数据到数据库失败: {str(e)}")
            raise
    
    async def _save_analysis_data_to_db(self, request: AnalysisResultRequest) -> None:
        """保存分析数据到数据库
        
        Args:
            request: 分析结果请求
        """
        try:
            # 直接保存到数据库
            SleepMonitoringMetrics.create(
                session_id=request.session_id,
                room_id=request.room_id,
                user_id=request.user_id,
                analysis_time=request.analysis_time,
                sleep_state=request.sleep_state,
                frequency_ratios=json.dumps(request.frequency_ratios),
                quality_score=request.quality_score,
                recommendations=json.dumps(request.recommendations)
            )
            
            logger.info(f"分析数据已保存到数据库: {request.session_id}")
            
        except Exception as e:
            logger.error(f"保存分析数据到数据库失败: {str(e)}")
            raise
            
            return {
                "id": brain_wave.id,
                "room_id": brain_wave.room_id,
                "user_id": brain_wave.user_id,
                "start_time": brain_wave.start_time.isoformat() if brain_wave.start_time else None,
                "end_time": brain_wave.end_time.isoformat() if brain_wave.end_time else None,
                "total_seconds": brain_wave.total_seconds,
                "created_at": brain_wave.created_at.isoformat() if brain_wave.created_at else None
            }
            
        except Exception as e:
            logger.error(f"获取会话数据失败: {str(e)}")
            return None
